<!DOCTYPE html>
<html lang="en-US">
    <head>
        <title>Parse::Yapp - Perl extension for generating and using LALR parsers. - metacpan.org</title>
        <link rel="preload" as="fetch" href="https://metacpan.org/account/login_status" crossorigin="anonymous" />
        <link href="https://metacpan.org/_assets/b8ccceeed47a0652049703d99326a9cea4933443.css" rel="stylesheet" type="text/css">
        <script src="https://metacpan.org/_assets/6bfedafe2d7caa915b7d84f61b45936818e3242e.js" type="text/javascript" defer></script>
        <link rel="alternate" type="application/rss+xml" title="Recent CPAN Uploads of Parse-Yapp - MetaCPAN" href="https://metacpan.org/dist/Parse-Yapp/releases.rss" />
        <link rel="canonical" href="./Parse::Yapp.html" />
        <meta name="description" content="Perl extension for generating and using LALR parsers." />
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">
        <link rel="shortcut icon" href="https://metacpan.org/static/icons/favicon.ico">
        <link rel="apple-touch-icon" sizes="152x152" href="https://metacpan.org/static/icons/apple-touch-icon.png">
        <link rel="search" href="https://metacpan.org/static/opensearch.xml" type="application/opensearchdescription+xml" title="MetaCPAN">
        <script>
          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

          (function(skey, ga_id){
            ga('create', ga_id, {
              siteSpeedSampleRate : 100,
              storage             : 'none',
              clientId            : localStorage.getItem(skey)
            });
            ga(function(tracker) {
              localStorage.setItem(skey, tracker.get('clientId'));
            });
            ga('send', 'pageview');
          })('ga:clientId', 'UA-27829474-1');
        </script>
<meta name="twitter:card"        content="summary" />
<meta name="twitter:url"         content="https://metacpan.org/pod/Parse::Yapp" />
<meta name="twitter:title"       content="Parse::Yapp" />
<meta name="twitter:description" content="Perl extension for generating and using LALR parsers." />
<meta name="twitter:site"        content="metacpan" />
    </head>
    <body>
        <nav class="navbar navbar-default" role="navigation">
            <div class="header-logo-large hidden-xs">
              <a href="https://metacpan.org/" tabindex="0">
                <svg class="logo" aria-label="MetaCPAN">
                  <use class="logo" href="/static/images/metacpan-logo.svg#logo" />
                </svg>
              </a>
            </div>
            <div class="header-logo-icon visible-xs">
              <a href="https://metacpan.org/">
                <svg class="logo" aria-label="MetaCPAN">
                  <use class="logo" href="/static/images/metacpan-logo.svg#dots" />
                </svg>
              </a>
            </div>
            <ul class="nav navbar-nav menu-items hidden-xs hidden-sm">
              <li><a href="https://metacpan.org/about">About</a></li>
              <li><a href="https://metacpan.org/about/sponsors">Sponsor</a></li>
              <li><a href="https://grep.metacpan.org/">grep::cpan</a></li>
              <li><a href="https://metacpan.org/recent">Recent</a></li>
              <li><a href="https://metacpan.org/about/faq">FAQ</a></li>
              <li><a href="https://metacpan.org/tools">Tools</a></li>
              <li><a href="https://fastapi.metacpan.org/">API</a></li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
                <button type="button" class="searchbar-btn visible-xs visible-sm">
                    <i class="fa fa-search button-fa-icon"></i>
                </button>
                <form action="https://metacpan.org/search" class="searchbar-form visible-md visible-lg search-form form-horizontal">
                   <input type="hidden" name="size" id="metacpan_search-size" value="20">
                  <div class="form-group">
                      <div class="search-group">
                        <i class="fa fa-search"></i>
                        <input type="text" name="q" placeholder="Search the CPAN" size="41" autocorrect="off" autocapitalize="off" spellcheck="false" id="metacpan_search-input" class="form-control" value="">
                      </div>
                  </div>
                </form>
                    <li class="icon-slidepanel visible-xs visible-sm">
                      <button data-toggle="slidepanel" data-target=".slidepanel">
                        <span class="button-fa-icon">
                          <i class="fa fa-bars slidepanel-open"></i>
                          <i class="fa fa-times slidepanel-close"></i>
                        </span>
                      </button>
                    </li>
                <form action="https://metacpan.org/account/logout" method="POST" id="metacpan-logout"></form>
                <li class="dropdown logged_in" style="display: none;">
                    <button type="button" class="dropdown-toggle" data-toggle="dropdown">
                      <i class="fa fa-user button-fa-icon logged-in-icon" aria-hidden="true"></i>
                      <i class="fas fa-chevron-down"></i>
                    </button>
                    <ul class="dropdown-menu">
                        <li><a href="https://metacpan.org/account/identities">Identities</a></li>
                        <li><a href="https://metacpan.org/account/profile">Profile</a></li>
                        <li><a href="https://metacpan.org/account/favorite/list">Favorites</a></li>
                        <li>
                            <a href="./Parse::Yapp.html#" type="button" onclick="$('#metacpan-logout').submit(); return false">
                              Logout
                            </a>
                        </li>
                    </ul>
                </li>
                <li class="dropdown logged_out" style="display: none;">
                    <button type="button" class="dropdown-toggle" data-toggle="dropdown">
                      <i class="fa fa-user button-fa-icon" aria-hidden="true"></i>
                      <i class="fas fa-chevron-down"></i>
                    </button>
                    <ul class="dropdown-menu">
                        <li>
                            <a href="https://metacpan.org/login/github">
                                <i class="fab fa-github fa-fw"></i>
                                GitHub
                            </a>
                        </li>
                        <li>
                            <a href="https://metacpan.org/login/twitter">
                                <i class="fab fa-twitter fa-fw"></i>
                                Twitter
                            </a>
                        </li>
                        <li>
                            <a href="https://metacpan.org/login/google">
                                <i class="fab fa-google fa-fw"></i>
                                Google
                            </a>
                        </li>
                    </ul>
                </li>
                <li class="dropdown logged_placeholder">
                    <button>
                      <i class="fa fa-user button-fa-icon" aria-hidden="true"></i>
                    </button>
                </li>
            </ul>
        </nav>
        <div class="page-content ">
          <!--
          <div class="top-notify-banner">
            <i class="fas fa-info-circle"></i>
          </div>
          -->
          <nav class="sidebar">
            <div class="slidepanel">
              <ul class="nav-list ">
    <li class="nav-header no-margin-top">
      <div class="ttip" data-toggle="tooltip" data-placement="bottom" title="The date that this version of Parse-Yapp was released.">
      <span class="relatize">04 Aug 2017 08:05:34 UTC</span>
    </li>
  <li>
    Distribution: <a href="https://metacpan.org/dist/Parse-Yapp">Parse-Yapp</a>
  </li>
  <li>
    Module version: 1.21
  </li>
  <li>
    <a data-keyboard-shortcut="g s" href="https://metacpan.org/dist/Parse-Yapp/source/lib/Parse/Yapp.pm">Source</a>
    (<a href="https://metacpan.org/dist/Parse-Yapp/source/lib/Parse/Yapp.pm?raw=1">raw</a>)
  </li>
  <li>
    <a data-keyboard-shortcut="g b" href="https://metacpan.org/dist/Parse-Yapp/source/lib/Parse">Browse</a>
    (<a href="https://metacpan.org/dist/Parse-Yapp/source/lib/Parse?raw=1">raw</a>)
  </li>
    <li>
      <a data-keyboard-shortcut="g c" href="https://metacpan.org/dist/Parse-Yapp/changes">Changes</a>
    </li>
    <li>
      <a class="nopopup" href="https://metacpan.org/dist/Parse-Yapp/contribute">How to Contribute</a>
    </li>
    <li>
      <a rel="noopener nofollow" data-keyboard-shortcut="g i" href="https://rt.cpan.org/Public/Dist/Display.html?Name=Parse-Yapp">Issues</a>
      (5)
    </li>
    <li>
      <a rel="noopener nofollow" href="http://matrix.cpantesters.org/?dist=Parse-Yapp+1.21" title="Matrix">Testers</a>
        <span title="(pass / fail / na)">(<a rel="noopener nofollow" href="https://www.cpantesters.org/distro/P/Parse-Yapp.html?oncpan=1&amp;distmat=1&amp;version=1.21&amp;grade=2" style="color: #090">517</a> / <a rel="noopener nofollow" href="https://www.cpantesters.org/distro/P/Parse-Yapp.html?oncpan=1&amp;distmat=1&amp;version=1.21&amp;grade=3" style="color: #900">0</a> / <a rel="noopener nofollow" href="https://www.cpantesters.org/distro/P/Parse-Yapp.html?oncpan=1&amp;distmat=1&amp;version=1.21&amp;grade=4">0</a>)</span>
    </li>
    <li>
      <a rel="noopener nofollow" href="http://cpants.cpanauthors.org/release/WBRASWELL/Parse-Yapp-1.21">Kwalitee</a>
    </li>
    <li>
      <div class="ttip" data-toggle="tooltip" data-placement="bottom" title="The # people with an indexing permission on Parse-Yapp who have released something to CPAN in the last 2 years (i.e. the # people likely able to release critical fixes in a timely manner)">
      Bus factor: 1
      </div>
    </li>
    <li>
      <a rel="noopener nofollow" href="http://cpancover.com/latest/Parse-Yapp-1.21/index.html">73.42% Coverage </a>
    </li>
    <li>
      License: unknown
    </li>
    <li class="nav-header">Activity</li>
    <li>
<div class="activity-graph">
    <img src="https://metacpan.org/dist/Parse-Yapp/activity.svg?res=month" />
    <div class="comment">24 month</div>
</div>
    </li>
    <li class="nav-header">Tools</li>
    <li>
      <a itemprop="downloadUrl" href="https://cpan.metacpan.org/authors/id/W/WB/WBRASWELL/Parse-Yapp-1.21.tar.gz">
      Download (<span itemprop="fileSize">106.11KB</span>)</a>
    </li>
    <li>
      <a href="https://explorer.metacpan.org/?url=%2Fmodule%2FWBRASWELL%2FParse-Yapp-1.21%2Flib%2FParse%2FYapp.pm">
        MetaCPAN Explorer
      </a>
    </li>
    <li>
      <a href="https://metacpan.org/dist/Parse-Yapp/permissions">
        Permissions
      </a>
    </li>
    <li>
      <a href="https://metacpan.org/dist/Parse-Yapp/releases.rss">
        Subscribe to distribution
      </a>
    </li>
    <li>
      <button class="btn btn-link" data-toggle="modal" data-target="#metacpan_install-instructions-dialog">
        Install Instructions
      </button>
    </li>
    <li>
      <form action="https://metacpan.org/search">
        <input type="hidden" name="q" value="dist:Parse-Yapp">
        <input type="search" name="q" placeholder="Search distribution" class="form-control tool-bar-form">
        <input type="submit" style="display: none">
      </form>
    </li>
    <li>
      <form action="https://grep.metacpan.org/search">
        <input type="hidden" name="qd" value="Parse-Yapp">
        <input type="hidden" name="source" value="metacpan">
        <input type="search" name="q" placeholder="grep distribution" class="form-control tool-bar-form">
        <input type="submit" style="display: none">
     </form>
    </li>
    <li class="version-jump">
<select onchange="document.location.href=&#39;/release/&#39;+this.value+&#39;/view/lib/Parse/Yapp.pm&#39;" class="form-control tool-bar-form">
  <option disabled selected>Jump to version</option>
<option
  disabled
  value="WBRASWELL/Parse-Yapp-1.21"
>1.21
  (WBRASWELL on 2017-08-04)</option>
<option
  
  value="WBRASWELL/Parse-Yapp-1.2"
>1.2
  (WBRASWELL on 2017-06-14)</option>
<option
  
  value="WBRASWELL/Parse-Yapp-1.06"
>1.06
  (WBRASWELL on 2017-06-14)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.05"
>1.05
  (FDESAR on 2001-11-05)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.04"
>1.04
  (FDESAR on 2001-02-12)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.03"
>1.03
  (FDESAR on 2000-11-05)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.02"
>1.02
  (FDESAR on 2000-05-01)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.01"
>1.01
  (FDESAR on 2000-03-28)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.00"
>1.00
  (FDESAR on 1999-10-20)</option>
<option
  
  value="FDESAR/Parse-Yapp-0.31"
>0.31
  (FDESAR on 1999-05-07)</option>
<option
  
  value="FDESAR/Parse-Yapp-0.30"
>0.30
  (FDESAR on 1999-04-03)</option>
<option
  
  value="FDESAR/Parse-Yapp-0.22"
>0.22
  (FDESAR on 1999-03-10)</option>
<optgroup label="BackPAN">'
<option
  
  value="FDESAR/Parse-Yapp-0.16"
>0.16
  (FDESAR on 1998-11-01)</option>
<option
  
  value="FDESAR/Parse-Yapp-0.15"
>0.15
  (FDESAR on 1998-08-17)</option>
<option
  
  value="FDESAR/Parse-Yapp-0.14"
>0.14
  (FDESAR on 1998-07-29)</option>
</optgroup>
</select>
    </li>
    <li class="version-diff">
<select onchange="document.location.href='/release/WBRASWELL/Parse-Yapp-1.21/diff/' + encodeURIComponent(this.value) + '/lib/Parse/Yapp.pm'
" class="form-control tool-bar-form">
  <option disabled selected>Diff with version</option>
<option
  disabled
  value="WBRASWELL/Parse-Yapp-1.21"
>1.21
  (WBRASWELL on 2017-08-04)</option>
<option
  
  value="WBRASWELL/Parse-Yapp-1.2"
>1.2
  (WBRASWELL on 2017-06-14)</option>
<option
  
  value="WBRASWELL/Parse-Yapp-1.06"
>1.06
  (WBRASWELL on 2017-06-14)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.05"
>1.05
  (FDESAR on 2001-11-05)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.04"
>1.04
  (FDESAR on 2001-02-12)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.03"
>1.03
  (FDESAR on 2000-11-05)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.02"
>1.02
  (FDESAR on 2000-05-01)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.01"
>1.01
  (FDESAR on 2000-03-28)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.00"
>1.00
  (FDESAR on 1999-10-20)</option>
<option
  
  value="FDESAR/Parse-Yapp-0.31"
>0.31
  (FDESAR on 1999-05-07)</option>
<option
  
  value="FDESAR/Parse-Yapp-0.30"
>0.30
  (FDESAR on 1999-04-03)</option>
<option
  
  value="FDESAR/Parse-Yapp-0.22"
>0.22
  (FDESAR on 1999-03-10)</option>
<optgroup label="BackPAN">'
<option
  
  value="FDESAR/Parse-Yapp-0.16"
>0.16
  (FDESAR on 1998-11-01)</option>
<option
  
  value="FDESAR/Parse-Yapp-0.15"
>0.15
  (FDESAR on 1998-08-17)</option>
<option
  
  value="FDESAR/Parse-Yapp-0.14"
>0.14
  (FDESAR on 1998-07-29)</option>
</optgroup>
</select>
    </li>

    <li>
<ul class="dependencies">
  <li class="nav-header">Dependencies</li>
  <li><i class="ttip" title="dynamic_config enabled">unknown</i></li>
  <li>
    <hr>
  </li>
  <li>
    <a href="https://metacpan.org/module/Parse::Yapp/requires">Reverse dependencies</a>
  </li>
  <li>
    <a href="http://deps.cpantesters.org/?module=Parse%3A%3AYapp">CPAN Testers List</a>
  </li>
  <li>
    <a href="https://cpandeps.grinnz.com/?dist=Parse-Yapp">Dependency graph</a>
  </li>
</ul>
    </li>
    <li class="nav-header">Permalinks</li>
    <li>
      <a href="https://metacpan.org/release/WBRASWELL/Parse-Yapp-1.21/view/lib/Parse/Yapp.pm">This version</a>
    </li>
    <li>
      <a href="./Parse::Yapp.html">Latest version</a>
    </li>
    <li>
<div class="plussers">
<div class="nav-header">++ed by:</div>
<div>
<a class="display-all" href="https://metacpan.org/author/ANNELI"><img src="https://www.gravatar.com/avatar/1368e76bbf9e732505a5598d17bc6143?d=identicon&amp;s=20" title="ANNELI" alt="ANNELI"></a>
<a class="display-all" href="https://metacpan.org/author/AMBS"><img src="https://www.gravatar.com/avatar/f647420229636bb7c7e65f659b8d2b21?d=identicon&amp;s=20" title="AMBS" alt="AMBS"></a>
<a class="display-all" href="https://metacpan.org/author/SYP"><img src="https://www.gravatar.com/avatar/9b6fa62677be03c25ee1af4d95472042?d=identicon&amp;s=20" title="SYP" alt="SYP"></a>
<a class="display-all" href="https://metacpan.org/author/KEEDI"><img src="https://www.gravatar.com/avatar/95f905a7a4ccc573c711e9d264c0fde8?d=identicon&amp;s=20" title="KEEDI" alt="KEEDI"></a>
</div>
<!-- Display counts of plussers-->
<div>
    <a href="https://metacpan.org/dist/Parse-Yapp/plussers">4 PAUSE users</a>
</div>
<div>
    1 non-PAUSE user
</div>
</div>
    </li>
    <li>
    </li>
              </ul>
            </div>
          </nav>
          <div class="content-navigation">
<div class="breadcrumbs">
  <span>
    <a data-keyboard-shortcut="g a" rel="author" href="https://metacpan.org/author/WBRASWELL" class="author-name">William N. Braswell, Jr.</a>
  </span>
  <span>&nbsp;/&nbsp;</span>
  <div class="release dist-release status-latest maturity-released">
    <span class="dropdown"><b class="caret"></b></span>
<select onchange="document.location.href=&#39;/release/&#39;+this.value+&#39;/view/lib/Parse/Yapp.pm&#39;" class="">
<option
  selected
  value="WBRASWELL/Parse-Yapp-1.21"
>1.21
  (WBRASWELL on 2017-08-04)</option>
<option
  
  value="WBRASWELL/Parse-Yapp-1.2"
>1.2
  (WBRASWELL on 2017-06-14)</option>
<option
  
  value="WBRASWELL/Parse-Yapp-1.06"
>1.06
  (WBRASWELL on 2017-06-14)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.05"
>1.05
  (FDESAR on 2001-11-05)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.04"
>1.04
  (FDESAR on 2001-02-12)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.03"
>1.03
  (FDESAR on 2000-11-05)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.02"
>1.02
  (FDESAR on 2000-05-01)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.01"
>1.01
  (FDESAR on 2000-03-28)</option>
<option
  
  value="FDESAR/Parse-Yapp-1.00"
>1.00
  (FDESAR on 1999-10-20)</option>
<option
  
  value="FDESAR/Parse-Yapp-0.31"
>0.31
  (FDESAR on 1999-05-07)</option>
<option
  
  value="FDESAR/Parse-Yapp-0.30"
>0.30
  (FDESAR on 1999-04-03)</option>
<option
  
  value="FDESAR/Parse-Yapp-0.22"
>0.22
  (FDESAR on 1999-03-10)</option>
<optgroup label="BackPAN">'
<option
  
  value="FDESAR/Parse-Yapp-0.16"
>0.16
  (FDESAR on 1998-11-01)</option>
<option
  
  value="FDESAR/Parse-Yapp-0.15"
>0.15
  (FDESAR on 1998-08-17)</option>
<option
  
  value="FDESAR/Parse-Yapp-0.14"
>0.14
  (FDESAR on 1998-07-29)</option>
</optgroup>
</select>
    <a data-keyboard-shortcut="g d" class="release-name" href="https://metacpan.org/dist/Parse-Yapp">Parse-Yapp-1.21</a>
  </div>
<span class="river-gauge-gauge">
  <svg width="24px"
       height="15px"
       version="1.1"
       xmlns="http://www.w3.org/2000/svg"
       xmlns:xlink="http://www.w3.org/1999/xlink">

    <g>
      <title>        River stage two &#10;
          • 21 direct dependents &#10;          • 46 total dependents
      </title>

      <rect x="0"  y="0" width="4" height="15" fill="#7ea3f2" />
      <rect x="5"  y="0" width="4" height="15" fill="#7ea3f2" />
      <rect x="10"  y="0" width="4" height="15" fill="#e4e2e2" />
      <rect x="15"  y="0" width="4" height="15" fill="#e4e2e2" />
      <rect x="20"  y="0" width="4" height="15" fill="#e4e2e2" />
    </g>
  </svg>

</span>
<div id="Parse-Yapp-fav" class="logged_in">
<form action="https://metacpan.org/account/favorite/add" style="display: inline" onsubmit="return favDistribution(this)">
    <input type="hidden" name="remove" value="0">
    <input type="hidden" name="release" value="Parse-Yapp-1.21">
    <input type="hidden" name="author" value="WBRASWELL">
    <input type="hidden" name="distribution" value="Parse-Yapp">
    <button type="submit" class="favorite highlight"><span>5</span> ++</button>
</form>
</div>
<div class="logged_out">
<a href="./Parse::Yapp.html" onclick="alert('Please sign in to add favorites'); return false" class="favorite highlight">
<span>5</span> ++</a>
</div>
   / <span>Parse::Yapp</span>
</div>
          </div>
          <main class="content">


<nav class="toc">
  <div class="toc-header"><strong>Contents</strong></div>
<ul>
  <li><a href="./Parse::Yapp.html#NAME">NAME</a></li>
  <li><a href="./Parse::Yapp.html#SYNOPSIS">SYNOPSIS</a></li>
  <li><a href="./Parse::Yapp.html#DESCRIPTION">DESCRIPTION</a>
    <ul>
      <li><a href="./Parse::Yapp.html#The-Grammar-file">The Grammar file</a></li>
    </ul>
  </li>
  <li><a href="./Parse::Yapp.html#BUGS-AND-SUGGESTIONS">BUGS AND SUGGESTIONS</a></li>
  <li><a href="./Parse::Yapp.html#AUTHOR">AUTHOR</a></li>
  <li><a href="./Parse::Yapp.html#SEE-ALSO">SEE ALSO</a></li>
  <li><a href="./Parse::Yapp.html#COPYRIGHT">COPYRIGHT</a></li>
</ul></nav>
<div class="pod anchors">
<h1 id="NAME">NAME</h1>

<p>Parse::Yapp - Perl extension for generating and using LALR parsers.</p>

<h1 id="SYNOPSIS">SYNOPSIS</h1>

<pre><code>  yapp -m MyParser grammar_file.yp

  ...

  use MyParser;

  $parser=new MyParser();
  $value=$parser-&gt;YYParse(yylex =&gt; \&amp;lexer_sub, yyerror =&gt; \&amp;error_sub);

  $nberr=$parser-&gt;YYNberr();

  $parser-&gt;YYData-&gt;{DATA}= [ &#39;Anything&#39;, &#39;You Want&#39; ];

  $data=$parser-&gt;YYData-&gt;{DATA}[0];</code></pre>

<h1 id="DESCRIPTION">DESCRIPTION</h1>

<p>Parse::Yapp (Yet Another Perl Parser compiler) is a collection of modules that let you generate and use yacc like thread safe (reentrant) parsers with perl object oriented interface.</p>

<p>The script yapp is a front-end to the Parse::Yapp module and let you easily create a Perl OO parser from an input grammar file.</p>

<h2 id="The-Grammar-file"><a id="The"></a>The Grammar file</h2>

<dl>

<dt id="Comments"><code>Comments</code></dt>
<dd>

<p>Through all your files, comments are either Perl style, introduced by <i>#</i> up to the end of line, or C style, enclosed between <i>/*</i> and <i>*/</i>.</p>

</dd>
<dt id="Tokens-and-string-literals"><a id="Tokens"></a><code>Tokens and string literals</code></dt>
<dd>

<p>Through all the grammar files, two kind of symbols may appear: <i>Non-terminal</i> symbols, called also <i>left-hand-side</i> symbols, which are the names of your rules, and <i>Terminal</i> symbols, called also <i>Tokens</i>.</p>

<p>Tokens are the symbols your lexer function will feed your parser with (see below). They are of two flavours: symbolic tokens and string literals.</p>

<p>Non-terminals and symbolic tokens share the same identifier syntax:</p>

<pre><code>                [A-Za-z][A-Za-z0-9_]*</code></pre>

<p>String literals are enclosed in single quotes and can contain almost anything. They will be output to your parser file double-quoted, making any special character as such. &#39;&quot;&#39;, &#39;$&#39; and &#39;@&#39; will be automatically quoted with &#39;\&#39;, making their writing more natural. On the other hand, if you need a single quote inside your literal, just quote it with &#39;\&#39;.</p>

<p>You cannot have a literal <i>&#39;error&#39;</i> in your grammar as it would confuse the driver with the <i>error</i> token. Use a symbolic token instead. In case you inadvertently use it, this will produce a warning telling you you should have written it <i>error</i> and will treat it as if it were the <i>error</i> token, which is certainly NOT what you meant.</p>

</dd>
<dt id="Grammar-file-syntax"><a id="Grammar"></a><code>Grammar file syntax</code></dt>
<dd>

<p>It is very close to yacc syntax (in fact, <i>Parse::Yapp</i> should compile a clean <i>yacc</i> grammar without any modification, whereas the opposite is not true).</p>

<p>This file is divided in three sections, separated by <code>%%</code>:</p>

<pre><code>        header section
        %%
        rules section
        %%
        footer section</code></pre>

<dl>

<dt id="The-Header-Section-section-may-optionally-contain:"><a id="The1"></a><a id="The-Header-Section-section-may-optionally-contain"></a><b>The Header Section</b> section may optionally contain:</dt>
<dd>

<ul>

<li><p>One or more code blocks enclosed inside <code>%{</code> and <code>%}</code> just like in yacc. They may contain any valid Perl code and will be copied verbatim at the very beginning of the parser module. They are not as useful as they are in yacc, but you can use them, for example, for global variable declarations, though you will notice later that such global variables can be avoided to make a reentrant parser module.</p>

</li>
<li><p>Precedence declarations, introduced by <code>%left</code>, <code>%right</code> and <code>%nonassoc</code> specifying associativity, followed by the list of tokens or litterals having the same precedence and associativity. The precedence being the latter declared will be having the highest level. (see the yacc or bison manuals for a full explanation of how they work, as they are implemented exactly the same way in Parse::Yapp)</p>

</li>
<li><p><code>%start</code> followed by a rule&#39;s left hand side, declaring this rule to be the starting rule of your grammar. The default, when <code>%start</code> is not used, is the first rule in your grammar section.</p>

</li>
<li><p><code>%token</code> followed by a list of symbols, forcing them to be recognized as tokens, generating a syntax error if used in the left hand side of a rule declaration. Note that in Parse::Yapp, you <i>don&#39;t</i> need to declare tokens as in yacc: any symbol not appearing as a left hand side of a rule is considered to be a token. Other yacc declarations or constructs such as <code>%type</code> and <code>%union</code> are parsed but (almost) ignored.</p>

</li>
<li><p><code>%expect</code> followed by a number, suppress warnings about number of Shift/Reduce conflicts when both numbers match, a la bison.</p>

</li>
</ul>

</dd>
</dl>

</dd>
<dt id="The-Rule-Section-contains-your-grammar-rules:"><a id="The2"></a><a id="The-Rule-Section-contains-your-grammar-rules"></a><b>The Rule Section</b> contains your grammar rules:</dt>
<dd>

<p>A rule is made of a left-hand-side symbol, followed by a <code>&#39;:&#39;</code> and one or more right-hand-sides separated by <code>&#39;|&#39;</code> and terminated by a <code>&#39;;&#39;</code>:</p>

<pre><code>    exp:    exp &#39;+&#39; exp
        |   exp &#39;-&#39; exp
        ;</code></pre>

<p>A right hand side may be empty:</p>

<pre><code>    input:  #empty
        |   input line
        ;</code></pre>

<p>(if you have more than one empty rhs, Parse::Yapp will issue a warning, as this is usually a mistake, and you will certainly have a reduce/reduce conflict)</p>

<p>A rhs may be followed by an optional <code>%prec</code> directive, followed by a token, giving the rule an explicit precedence (see yacc manuals for its precise meaning) and optional semantic action code block (see below).</p>

<pre><code>    exp:   &#39;-&#39; exp %prec NEG { -$_[1] }
        |  exp &#39;+&#39; exp       { $_[1] + $_[3] }
        |  NUM
        ;</code></pre>

<p>Note that in Parse::Yapp, a lhs <i>cannot</i> appear more than once as a rule name (This differs from yacc).</p>

</dd>
<dt id="The-footer-section"><a id="The3"></a><code>The footer section</code></dt>
<dd>

<p>may contain any valid Perl code and will be appended at the very end of your parser module. Here you can write your lexer, error report subs and anything relevant to you parser.</p>

</dd>
<dt id="Semantic-actions"><a id="Semantic"></a><code>Semantic actions</code></dt>
<dd>

<p>Semantic actions are run every time a <i>reduction</i> occurs in the parsing flow and they must return a semantic value.</p>

<p>They are (usually, but see below <code>In rule actions</code>) written at the very end of the rhs, enclosed with <code>{ }</code>, and are copied verbatim to your parser file, inside of the rules table.</p>

<p>Be aware that matching braces in Perl is much more difficult than in C: inside strings they don&#39;t need to match. While in C it is very easy to detect the beginning of a string construct, or a single character, it is much more difficult in Perl, as there are so many ways of writing such literals. So there is no check for that today. If you need a brace in a double-quoted string, just quote it (<code>\{</code> or <code>\}</code>). For single-quoted strings, you will need to make a comment matching it <i>in th right order</i>. Sorry for the inconvenience.</p>

<pre><code>    {
        &quot;{ My string block }&quot;.
        &quot;\{ My other string block \}&quot;.
        qq/ My unmatched brace \} /.
        # Force the match: {
        q/ for my closing brace } /
        q/ My opening brace { /
        # must be closed: }
    }</code></pre>

<p>All of these constructs should work.</p>

<p>In Parse::Yapp, semantic actions are called like normal Perl sub calls, with their arguments passed in <code>@_</code>, and their semantic value are their return values.</p>

<p>$_[1] to $_[n] are the parameters just as $1 to $n in yacc, while $_[0] is the parser object itself.</p>

<p>Having $_[0] being the parser object itself allows you to call parser methods. That&#39;s how the yacc macros are implemented:</p>

<pre><code>        yyerrok is done by calling $_[0]-&gt;YYErrok
        YYERROR is done by calling $_[0]-&gt;YYError
        YYACCEPT is done by calling $_[0]-&gt;YYAccept
        YYABORT is done by calling $_[0]-&gt;YYAbort</code></pre>

<p>All those methods explicitly return <i>undef</i>, for convenience.</p>

<pre><code>    YYRECOVERING is done by calling $_[0]-&gt;YYRecovering</code></pre>

<p>Four useful methods in error recovery sub</p>

<pre><code>    $_[0]-&gt;YYCurtok
    $_[0]-&gt;YYCurval
    $_[0]-&gt;YYExpect
    $_[0]-&gt;YYLexer</code></pre>

<p>return respectivly the current input token that made the parse fail, its semantic value (both can be used to modify their values too, but <i>know what you are doing</i> ! See <i>Error reporting routine</i> section for an example), a list which contains the tokens the parser expected when the failure occurred and a reference to the lexer routine.</p>

<p>Note that if <code>$_[0]-&gt;YYCurtok</code> is declared as a <code>%nonassoc</code> token, it can be included in <code>$_[0]-&gt;YYExpect</code> list whenever the input try to use it in an associative way. This is not a bug: the token IS expected to report an error if encountered.</p>

<p>To detect such a thing in your error reporting sub, the following example should do the trick:</p>

<pre><code>        grep { $_[0]-&gt;YYCurtok eq $_ } $_[0]-&gt;YYExpect
    and do {
        #Non-associative token used in an associative expression
    };</code></pre>

<p>Accessing semantics values on the left of your reducing rule is done through the method</p>

<pre><code>    $_[0]-&gt;YYSemval( index )</code></pre>

<p>where index is an integer. Its value being <i>1 .. n</i> returns the same values than <i>$_[1] .. $_[n]</i>, but <i>-n .. 0</i> returns values on the left of the rule being reduced (It is related to <i>$-n .. $0 .. $n</i> in yacc, but you cannot use <i>$_[0]</i> or <i>$_[-n]</i> constructs in Parse::Yapp for obvious reasons)</p>

<p>There is also a provision for a user data area in the parser object, accessed by the method:</p>

<pre><code>    $_[0]-&gt;YYData</code></pre>

<p>which returns a reference to an anonymous hash, which let you have all of your parsing data held inside the object (see the Calc.yp or ParseYapp.yp files in the distribution for some examples). That&#39;s how you can make you parser module reentrant: all of your module states and variables are held inside the parser object.</p>

<p>Note: unfortunately, method calls in Perl have a lot of overhead, and when YYData is used, it may be called a huge number of times. If your are not a *real* purist and efficiency is your concern, you may access directly the user-space in the object: $parser-&gt;{USER} wich is a reference to an anonymous hash array, and then benchmark.</p>

<p>If no action is specified for a rule, the equivalant of a default action is run, which returns the first parameter:</p>

<pre><code>   { $_[1] }</code></pre>

</dd>
<dt id="In-rule-actions"><a id="In"></a><code>In rule actions</code></dt>
<dd>

<p>It is also possible to embed semantic actions inside of a rule:</p>

<pre><code>    typedef:    TYPE { $type = $_[1] } identlist { ... } ;</code></pre>

<p>When the Parse::Yapp&#39;s parser encounter such an embedded action, it modifies the grammar as if you wrote (although @x-1 is not a legal lhs value):</p>

<pre><code>    @x-1:   /* empty */ { $type = $_[1] };
    typedef:    TYPE @x-1 identlist { ... } ;</code></pre>

<p>where <i>x</i> is a sequential number incremented for each &quot;in rule&quot; action, and <i>-1</i> represents the &quot;dot position&quot; in the rule where the action arises.</p>

<p>In such actions, you can use <i>$_[1]..$_[n]</i> variables, which are the semantic values on the left of your action.</p>

<p>Be aware that the way Parse::Yapp modifies your grammar because of <i>in rule actions</i> can produce, in some cases, spurious conflicts that wouldn&#39;t happen otherwise.</p>

</dd>
<dt id="Generating-the-Parser-Module"><a id="Generating"></a><code>Generating the Parser Module</code></dt>
<dd>

<p>Now that you grammar file is written, you can use yapp on it to generate your parser module:</p>

<pre><code>    yapp -v Calc.yp</code></pre>

<p>will create two files <i>Calc.pm</i>, your parser module, and <i>Calc.output</i> a verbose output of your parser rules, conflicts, warnings, states and summary.</p>

<p>What your are missing now is a lexer routine.</p>

</dd>
<dt id="The-Lexer-sub"><a id="The4"></a><code>The Lexer sub</code></dt>
<dd>

<p>is called each time the parser need to read the next token.</p>

<p>It is called with only one argument that is the parser object itself, so you can access its methods, specially the</p>

<pre><code>    $_[0]-&gt;YYData</code></pre>

<p>data area.</p>

<p>It is its duty to return the next token and value to the parser. They <code>must</code> be returned as a list of two variables, the first one is the token known by the parser (symbolic or literal), the second one being anything you want (usually the content of the token, or the literal value) from a simple scalar value to any complex reference, as the parsing driver never use it but to call semantic actions:</p>

<pre><code>    ( &#39;NUMBER&#39;, $num )
or
    ( &#39;&gt;=&#39;, &#39;&gt;=&#39; )
or
    ( &#39;ARRAY&#39;, [ @values ] )</code></pre>

<p>When the lexer reach the end of input, it must return the <code>&#39;&#39;</code> empty token with an undef value:</p>

<pre><code>     ( &#39;&#39;, undef )</code></pre>

<p>Note that your lexer should <i>never</i> return <code>&#39;error&#39;</code> as token value: for the driver, this is the error token used for error recovery and would lead to odd reactions.</p>

<p>Now that you have your lexer written, maybe you will need to output meaningful error messages, instead of the default which is to print &#39;Parse error.&#39; on STDERR.</p>

<p>So you will need an Error reporting sub.</p>

</dd>
<dt id="Error-reporting-routine"><a id="Error"></a><code>Error reporting routine</code></dt>
<dd>

<p>If you want one, write it knowing that it is passed as parameter the parser object. So you can share information with the lexer routine quite easily.</p>

<p>You can also use the <code>$_[0]-&gt;YYErrok</code> method in it, which will resume parsing as if no error occurred. Of course, since the invalid token is still invalid, you&#39;re supposed to fix the problem by yourself.</p>

<p>The method <code>$_[0]-&gt;YYLexer</code> may help you, as it returns a reference to the lexer routine, and can be called as</p>

<pre><code>    ($tok,$val)=&amp;{$_[0]-&gt;Lexer}</code></pre>

<p>to get the next token and semantic value from the input stream. To make them current for the parser, use:</p>

<pre><code>    ($_[0]-&gt;YYCurtok, $_[0]-&gt;YYCurval) = ($tok, $val)</code></pre>

<p>and know what you&#39;re doing...</p>

</dd>
<dt id="Parsing"><code>Parsing</code></dt>
<dd>

<p>Now you&#39;ve got everything to do the parsing.</p>

<p>First, use the parser module:</p>

<pre><code>    use Calc;</code></pre>

<p>Then create the parser object:</p>

<pre><code>    $parser=new Calc;</code></pre>

<p>Now, call the YYParse method, telling it where to find the lexer and error report subs:</p>

<pre><code>    $result=$parser-&gt;YYParse(yylex =&gt; \&amp;Lexer,
                           yyerror =&gt; \&amp;ErrorReport);</code></pre>

<p>(assuming Lexer and ErrorReport subs have been written in your current package)</p>

<p>The order in which parameters appear is unimportant.</p>

<p>Et voila.</p>

<p>The YYParse method will do the parse, then return the last semantic value returned, or undef if error recovery cannot recover.</p>

<p>If you need to be sure the parse has been successful (in case your last returned semantic value <i>is</i> undef) make a call to:</p>

<pre><code>    $parser-&gt;YYNberr()</code></pre>

<p>which returns the total number of time the error reporting sub has been called.</p>

</dd>
<dt id="Error-Recovery"><a id="Error1"></a><code>Error Recovery</code></dt>
<dd>

<p>in Parse::Yapp is implemented the same way it is in yacc.</p>

</dd>
<dt id="Debugging-Parser"><a id="Debugging"></a><code>Debugging Parser</code></dt>
<dd>

<p>To debug your parser, you can call the YYParse method with a debug parameter:</p>

<pre><code>    $parser-&gt;YYParse( ... , yydebug =&gt; value, ... )</code></pre>

<p>where value is a bitfield, each bit representing a specific debug output:</p>

<pre><code>    Bit Value    Outputs
    0x01         Token reading (useful for Lexer debugging)
    0x02         States information
    0x04         Driver actions (shifts, reduces, accept...)
    0x08         Parse Stack dump
    0x10         Error Recovery tracing</code></pre>

<p>To have a full debugging output, use</p>

<pre><code>    debug =&gt; 0x1F</code></pre>

<p>Debugging output is sent to STDERR, and be aware that it can produce <code>huge</code> outputs.</p>

</dd>
<dt id="Standalone-Parsers"><a id="Standalone"></a><code>Standalone Parsers</code></dt>
<dd>

<p>By default, the parser modules generated will need the Parse::Yapp module installed on the system to run. They use the Parse::Yapp::Driver which can be safely shared between parsers in the same script.</p>

<p>In the case you&#39;d prefer to have a standalone module generated, use the <code>-s</code> switch with yapp: this will automagically copy the driver code into your module so you can use/distribute it without the need of the Parse::Yapp module, making it really a <code>Standalone Parser</code>.</p>

<p>If you do so, please remember to include Parse::Yapp&#39;s copyright notice in your main module copyright, so others can know about Parse::Yapp module.</p>

</dd>
<dt id="Source-file-line-numbers"><a id="Source"></a><code>Source file line numbers</code></dt>
<dd>

<p>by default will be included in the generated parser module, which will help to find the guilty line in your source file in case of a syntax error. You can disable this feature by compiling your grammar with yapp using the <code>-n</code> switch.</p>

</dd>
</dl>

<h1 id="BUGS-AND-SUGGESTIONS"><a id="BUGS"></a>BUGS AND SUGGESTIONS</h1>

<p>If you find bugs, think of anything that could improve Parse::Yapp or have any questions related to it, feel free to contact the author.</p>

<h1 id="AUTHOR">AUTHOR</h1>

<p>William N. Braswell, Jr. &lt;wbraswell_cpan@NOSPAM.nym.hush.com&gt; (Remove &quot;NOSPAM&quot;.)</p>

<h1 id="SEE-ALSO"><a id="SEE"></a>SEE ALSO</h1>

<p>yapp(1) perl(1) yacc(1) bison(1).</p>

<h1 id="COPYRIGHT">COPYRIGHT</h1>

<p>The Parse::Yapp module and its related modules and shell scripts are copyright: Copyright &copy; 1998, 1999, 2000, 2001, Francois Desarmenien. Copyright &copy; 2017 William N. Braswell, Jr.</p>

<p>You may use and distribute them under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file.</p>

<p>If you use the &quot;standalone parser&quot; option so people don&#39;t need to install Parse::Yapp on their systems in order to run you software, this copyright noticed should be included in your software copyright too, and the copyright notice in the embedded driver should be left untouched.</p></div>

<div id="metacpan_install-instructions-dialog" class="modal fade">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
        <h4 class="modal-title">Module Install Instructions</h4>
      </div>
      <div class="modal-body">
        <p>To install Parse::Yapp, copy and paste the appropriate command in to your terminal.</p>
        <p><a href="https://metacpan.org/dist/App-cpanminus/view/bin/cpanm">cpanm</a></p>
        <pre><code>cpanm Parse::Yapp</code></pre>
        <p><a href="https://metacpan.org/pod/CPAN">CPAN shell</a></p>
        <pre><code>perl -MCPAN -e shell
install Parse::Yapp</code></pre>
        <p>For more information on module installation, please visit <a href="https://www.cpan.org/modules/INSTALL.html">the detailed CPAN module installation guide</a>.</p>
      </div>
      <div class="modal-footer">
        <a href="./Parse::Yapp.html#" data-dismiss="modal" class="btn">Close</a>
      </div>
    </div>
  </div>
</div>
          </main>
          <div class="content-pagination">
          </div>
        </div>
        <footer class="footer">
          <div class="footer-container">
            <div class="footer-social">
              <div class="footer-link footer-logo">
                <a href="https://metacpan.org/">
                  <img src="https://metacpan.org/static/images/metacpan-logo.svg" alt="MetaCPAN" />
                </a>
              </div>
              <a class="footer-social-link" href="https://github.com/metacpan">
                <i class="fab fa-github-square"></i>
              </a>
              <a class="footer-social-link" href="https://fosstodon.org/@metacpan">
                <i class="fab fa-mastodon"></i>
              </a>
            </div>
            <div class="footer-links">
              <div class="footer-link">
                  <a href="https://metacpan.org/about">About</a>
              </div>
              <div class="footer-link">
                  <a href="https://metacpan.org/about/sponsors">Sponsor</a>
              </div>
              <div class="footer-link">
                  <a href="https://grep.metacpan.org">grep::cpan</a>
              </div>
              <div class="footer-link">
                  <a href="https://metacpan.org/recent">Recent</a>
              </div>
              <div class="footer-link">
                  <a href="https://metacpan.org/about/faq">FAQ</a>
              </div>
              <div class="footer-link">
                  <a href="https://metacpan.org/tools">Tools</a>
              </div>
              <div class="footer-link">
                  <a href="https://fastapi.metacpan.org/">API</a>
              </div>
              <div class="footer-link">
                  <a href="https://www.perl.org/">Perl.org</a>
              </div>
            </div>
            <div class="footer-sponsors">
              <a class="footer-sponsor-link" target="_blank" href="https://www.bytemark.co.uk/" rel="noopener">
                <img class="footer-sponsor-bytemark" src="https://metacpan.org/static/images/sponsors/bytemark_logo.svg" alt="Bytemark logo">
              </a>
              <a class="footer-sponsor-link" target="_blank" href="https://www.liquidweb.com/" rel="noopener">
                <img class="footer-sponsor-liquidweb" src="https://metacpan.org/static/images/sponsors/liquidweb_logo.png" alt="liquidweb logo">
              </a>
              <a class="footer-sponsor-link" target="_blank" href="https://deriv.com/careers/" rel="noopener">
                <img class="footer-sponsor-deriv" src="https://metacpan.org/static/images/sponsors/deriv.svg" alt="Deriv logo">
              </a>
              <a class="footer-sponsor-link" target="_blank" href="https://geocode.xyz" rel="noopener">
                <img class="footer-sponsor-geocode" src="https://metacpan.org/static/images/sponsors/geocodelogo.svg" alt="Geocode logo">
              </a>
              <a class="footer-sponsor-link" target="_blank" href="https://www.fastly.com/" rel="noopener">
                <img class="footer-sponsor-fastly" src="https://metacpan.org/static/images/sponsors/fastly_logo.svg" alt="Fastly logo">
              </a>
              <a class="footer-sponsor-link" target="_blank" href="https://opencagedata.com" rel="noopener">
                <img class="footer-sponsor-opencage" src="https://metacpan.org/static/images/sponsors/open-cage.svg" alt="OpenCage logo">
              </a>
            </div>
          </div>
        </footer>
        <div class="modal fade" tabindex="-1" role="dialog" id="metacpan_keyboard-shortcuts">
          <div class="modal-dialog">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal">&times;</button>
                <h4 class="modal-title">Keyboard Shortcuts</h4>
              </div>
              <div class="modal-body row">
<div class="col-md-6">
  <table class="table keyboard-shortcuts">
    <thead>
      <tr>
        <th></th>
        <th>Global</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td class="keys">
          <kbd>s</kbd>
        </td>
        <td>Focus search bar</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>?</kbd>
        </td>
        <td>Bring up this help dialog</td>
      </tr>
    </tbody>
  </table>

  <table class="table keyboard-shortcuts">
    <thead>
      <tr>
        <th></th>
        <th>GitHub</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>p</kbd>
        </td>
        <td>Go to pull requests</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>i</kbd>
        </td>
        <td>go to github issues (only if github is preferred repository)</td>
      </tr>
    </tbody>
  </table>
</div>

<div class="col-md-6">
  <table class="table keyboard-shortcuts">
    <thead>
      <tr>
        <th></th>
        <th>POD</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>a</kbd>
        </td>
        <td>Go to author</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>c</kbd>
        </td>
        <td>Go to changes</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>i</kbd>
        </td>
        <td>Go to issues</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>d</kbd>
        </td>
        <td>Go to dist</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>r</kbd>
        </td>
        <td>Go to repository/SCM</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>s</kbd>
        </td>
        <td>Go to source</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>b</kbd>
        </td>
        <td>Go to file browse</td>
      </tr>

    </tbody>
  </table>
</div>

<div class="col-md-12">
  <table class="table keyboard-shortcuts">
    <thead>
      <tr>
        <th></th>
        <th>Search terms</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><em>module:</em> (e.g. <a href="https://metacpan.org/search?q=module%3APlugin">module:Plugin</a>)</td>
      </tr>
      <tr>
        <td><em>distribution:</em> (e.g. <a href="https://metacpan.org/search?q=distribution%3ADancer+auth">distribution:Dancer auth</a>)</td>
      </tr>
      <tr>
        <td><em>author:</em> (e.g. <a href="https://metacpan.org/search?q=author%3ASONGMU+Redis">author:SONGMU Redis</a>)</td>
      </tr>
      <tr>
        <td><em>version:</em> (e.g. <a href="https://metacpan.org/search?q=version%3A1.00">version:1.00</a>)</td>
      </tr>
    </tbody>
  </table>
</div>
              </div>
              <div class="modal-footer"></div>
            </div>
          </div>
        </div>
    </body>
</html>
